package hello;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Date;
import java.util.concurrent.CountDownLatch;

import hello.test.TestService;
import mapper.CronMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronSequenceGenerator;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import javax.servlet.http.HttpServletRequest;

@RestController
@EnableWebMvc
@SpringBootApplication
@EnableScheduling
@ComponentScan(
		basePackages = {"hello"}
)
@EnableTransactionManagement
public class Application implements SchedulingConfigurer {

	private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);


	@Mapper
	public interface CronMapper {
		@Select("select cron from cron limit 1")
		String getCron();
	}

	@Autowired
	@SuppressWarnings("all")
	CronMapper cronMapper;

	@RequestMapping(value = "login")
	public String login(HttpServletRequest request){
		request.getSession().setAttribute("aa","new session");
		return "{\"sucess\":\"1\"}";
	}

	@Bean
	RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
			MessageListenerAdapter listenerAdapter) {

		RedisMessageListenerContainer container = new RedisMessageListenerContainer();
		container.setConnectionFactory(connectionFactory);
		container.addMessageListener(listenerAdapter, new PatternTopic("chat"));

		return container;
	}

	@Bean
	MessageListenerAdapter listenerAdapter(Receiver receiver) {
		return new MessageListenerAdapter(receiver, "receiveMessage");
	}

	@Bean
	Receiver receiver(CountDownLatch latch) {
		return new Receiver(latch);
	}


	@Bean
	MessageConsumerService messageConsumerService() {
		return new MessageConsumerService();
	}

	@Bean
	MessageProducerService messageProducerService() {
		return new MessageProducerService();
	}

	@Bean
	CountDownLatch latch() {
		return new CountDownLatch(1);
	}

	@Bean(name = "redisTemplate")
	RedisTemplate<?, ?> template(RedisConnectionFactory connectionFactory) {
		RedisTemplate<?, ?> redisTemplate = new RedisTemplate<>();
		redisTemplate.setConnectionFactory(connectionFactory);
		redisTemplate.setKeySerializer(new StringRedisSerializer());
		redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
		return redisTemplate;
	}


	public static void main(String[] args) throws InterruptedException {

		ApplicationContext ctx = SpringApplication.run(Application.class, args);

		TestService testService = (TestService) ctx.getBean("testService");
		testService.test();



//		template.convertAndSend("chat", new Message("1", "消息"));
//		messageConsumerService.start();
//		int i = 0;
//		while (true){
//			messageProducerService.sendMessage(new Message(i + "", "消息"));
//			if (i % 10 == 0) {
//				Thread.sleep(10000L);
//			}
//			i++;
//		}

//		System.exit(0);
	}

	@Override
	public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
		taskRegistrar.addTriggerTask(
				//1.添加任务内容(Runnable)
				() -> System.out.println("执行定时任务2: " + LocalDateTime.now().toLocalTime()),
				//2.设置执行周期(Trigger)
				triggerContext -> {
					//2.1 从数据库获取执行周期
					String cron = cronMapper.getCron();
					//2.2 合法性校验.
					if (StringUtils.isEmpty(cron)) {
						// Omitted Code ..
					}

					CronSequenceGenerator generator = new CronSequenceGenerator(cron);
					SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
					Date nextTime = generator.next(new Date());
					System.out.println(format.format(nextTime));
					//2.3 返回执行周期(Date)
					return new CronTrigger(cron).nextExecutionTime(triggerContext);
				}
		);



		ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
		threadPoolTaskScheduler.setPoolSize(20);
		threadPoolTaskScheduler.setThreadNamePrefix("scheduled-task-pool-");
		threadPoolTaskScheduler.initialize();
		taskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
	}
}
